# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: site-packages\gevent\libev\corecffi.py
from __future__ import absolute_import, print_function
import sys, os, traceback, signal as signalmodule

__all__ = [
    "get_version",
    "get_header_version",
    "supported_backends",
    "recommended_backends",
    "embeddable_backends",
    "time",
    "loop",
]
import gevent.libev._corecffi as _corecffi

ffi = _corecffi.ffi
libev = _corecffi.lib
if hasattr(libev, "vfd_open"):
    if not sys.platform.startswith("win"):
        raise AssertionError("vfd functions only needed on windows")
    vfd_open = libev.vfd_open
    vfd_free = libev.vfd_free
    vfd_get = libev.vfd_get
else:
    vfd_open = vfd_free = vfd_get = lambda fd: fd


@ffi.callback("int(void* handle, int revents)")
def _python_callback(handle, revents):
    """
    Returns an integer having one of three values:
    
    - -1
      An exception occurred during the callback and you must call
      :func:`_python_handle_error` to deal with it. The Python watcher
      object will have the exception tuple saved in ``_exc_info``.
    - 0
      Everything went according to plan. You should check to see if the libev
      watcher is still active, and call :func:`_python_stop` if so. This will
      clean up the memory.
    - 1
      Everything went according to plan, but the watcher has already
      been stopped. Its memory may no longer be valid.
    """
    try:
        the_watcher = ffi.from_handle(handle)
        args = the_watcher.args
        if args is None:
            args = _NOARGS
        if args:
            if args[0] == GEVENT_CORE_EVENTS:
                args = (revents,) + args[1:]
        the_watcher.callback(*args)
    except:
        the_watcher._exc_info = sys.exc_info()
        the_watcher.loop._keepaliveset.add(the_watcher)
        return -1

    if the_watcher in the_watcher.loop._keepaliveset:
        return 0
    else:
        return 1


libev.python_callback = _python_callback


@ffi.callback("void(void* handle, int revents)")
def _python_handle_error(handle, revents):
    try:
        watcher = ffi.from_handle(handle)
        exc_info = watcher._exc_info
        del watcher._exc_info
        watcher.loop.handle_error(watcher, *exc_info)
    finally:
        if revents & (libev.EV_READ | libev.EV_WRITE):
            try:
                watcher.stop()
            except:
                watcher.loop.handle_error(watcher, *sys.exc_info())

            return


libev.python_handle_error = _python_handle_error


@ffi.callback("void(void* handle)")
def _python_stop(handle):
    watcher = ffi.from_handle(handle)
    watcher.stop()


libev.python_stop = _python_stop
UNDEF = libev.EV_UNDEF
NONE = libev.EV_NONE
READ = libev.EV_READ
WRITE = libev.EV_WRITE
TIMER = libev.EV_TIMER
PERIODIC = libev.EV_PERIODIC
SIGNAL = libev.EV_SIGNAL
CHILD = libev.EV_CHILD
STAT = libev.EV_STAT
IDLE = libev.EV_IDLE
PREPARE = libev.EV_PREPARE
CHECK = libev.EV_CHECK
EMBED = libev.EV_EMBED
FORK = libev.EV_FORK
CLEANUP = libev.EV_CLEANUP
ASYNC = libev.EV_ASYNC
CUSTOM = libev.EV_CUSTOM
ERROR = libev.EV_ERROR
READWRITE = libev.EV_READ | libev.EV_WRITE
MINPRI = libev.EV_MINPRI
MAXPRI = libev.EV_MAXPRI
BACKEND_PORT = libev.EVBACKEND_PORT
BACKEND_KQUEUE = libev.EVBACKEND_KQUEUE
BACKEND_EPOLL = libev.EVBACKEND_EPOLL
BACKEND_POLL = libev.EVBACKEND_POLL
BACKEND_SELECT = libev.EVBACKEND_SELECT
FORKCHECK = libev.EVFLAG_FORKCHECK
NOINOTIFY = libev.EVFLAG_NOINOTIFY
SIGNALFD = libev.EVFLAG_SIGNALFD
NOSIGMASK = libev.EVFLAG_NOSIGMASK


class _EVENTSType(object):
    def __repr__(self):
        return "gevent.core.EVENTS"


EVENTS = GEVENT_CORE_EVENTS = _EVENTSType()


def get_version():
    return "libev-%d.%02d" % (libev.ev_version_major(), libev.ev_version_minor())


def get_header_version():
    return "libev-%d.%02d" % (libev.EV_VERSION_MAJOR, libev.EV_VERSION_MINOR)


_flags = [
    (libev.EVBACKEND_PORT, "port"),
    (libev.EVBACKEND_KQUEUE, "kqueue"),
    (libev.EVBACKEND_EPOLL, "epoll"),
    (libev.EVBACKEND_POLL, "poll"),
    (libev.EVBACKEND_SELECT, "select"),
    (libev.EVFLAG_NOENV, "noenv"),
    (libev.EVFLAG_FORKCHECK, "forkcheck"),
    (libev.EVFLAG_SIGNALFD, "signalfd"),
    (libev.EVFLAG_NOSIGMASK, "nosigmask"),
]
_flags_str2int = dict(((string, flag) for flag, string in _flags))
_events = [
    (libev.EV_READ, "READ"),
    (libev.EV_WRITE, "WRITE"),
    (libev.EV__IOFDSET, "_IOFDSET"),
    (libev.EV_PERIODIC, "PERIODIC"),
    (libev.EV_SIGNAL, "SIGNAL"),
    (libev.EV_CHILD, "CHILD"),
    (libev.EV_STAT, "STAT"),
    (libev.EV_IDLE, "IDLE"),
    (libev.EV_PREPARE, "PREPARE"),
    (libev.EV_CHECK, "CHECK"),
    (libev.EV_EMBED, "EMBED"),
    (libev.EV_FORK, "FORK"),
    (libev.EV_CLEANUP, "CLEANUP"),
    (libev.EV_ASYNC, "ASYNC"),
    (libev.EV_CUSTOM, "CUSTOM"),
    (libev.EV_ERROR, "ERROR"),
]


def _flags_to_list(flags):
    result = []
    for code, value in _flags:
        if flags & code:
            result.append(value)
        flags &= ~code
        if not flags:
            break

    if flags:
        result.append(flags)
    return result


if sys.version_info[0] >= 3:
    basestring = (bytes, str)
    integer_types = (int,)
else:
    import __builtin__

    basestring = (__builtin__.basestring,)
    integer_types = (int, __builtin__.long)


def _flags_to_int(flags):
    if not flags:
        return 0
    elif isinstance(flags, integer_types):
        return flags
    else:
        result = 0
        try:
            if isinstance(flags, basestring):
                flags = flags.split(",")
            for value in flags:
                value = value.strip().lower()
                if value:
                    result |= _flags_str2int[value]

        except KeyError as ex:
            raise ValueError(
                "Invalid backend or flag: %s\nPossible values: %s"
                % (ex, (", ").join(sorted(_flags_str2int.keys())))
            )

        return result


def _str_hex(flag):
    if isinstance(flag, integer_types):
        return hex(flag)
    else:
        return str(flag)


def _check_flags(flags):
    as_list = []
    flags &= libev.EVBACKEND_MASK
    if not flags:
        return
    if not flags & libev.EVBACKEND_ALL:
        raise ValueError("Invalid value for backend: 0x%x" % flags)
    if not flags & libev.ev_supported_backends():
        as_list = [_str_hex(x) for x in _flags_to_list(flags)]
        raise ValueError("Unsupported backend: %s" % ("|").join(as_list))


def _events_to_str(events):
    result = []
    for flag, string in _events:
        c_flag = flag
        if events & c_flag:
            result.append(string)
            events = events & ~c_flag
        if not events:
            break

    if events:
        result.append(hex(events))
    return ("|").join(result)


def supported_backends():
    return _flags_to_list(libev.ev_supported_backends())


def recommended_backends():
    return _flags_to_list(libev.ev_recommended_backends())


def embeddable_backends():
    return _flags_to_list(libev.ev_embeddable_backends())


def time():
    return libev.ev_time()


_default_loop_destroyed = False


def _loop_callback(*args, **kwargs):
    return ffi.callback(*args, **kwargs)


class loop(object):
    error_handler = None

    def __init__(self, flags=None, default=None):
        global _default_loop_destroyed
        self._in_callback = False
        self._callbacks = []
        self._check = ffi.new("struct ev_check *")
        self._check_callback_ffi = _loop_callback(
            "void(*)(struct ev_loop *, void*, int)",
            self._check_callback,
            onerror=self._check_callback_handle_error,
        )
        libev.ev_check_init(self._check, self._check_callback_ffi)
        self._prepare = ffi.new("struct ev_prepare *")
        self._prepare_callback_ffi = _loop_callback(
            "void(*)(struct ev_loop *, void*, int)",
            self._run_callbacks,
            onerror=self._check_callback_handle_error,
        )
        libev.ev_prepare_init(self._prepare, self._prepare_callback_ffi)
        self._timer0 = ffi.new("struct ev_timer *")
        libev.ev_timer_init(self._timer0, libev.gevent_noop, 0.0, 0.0)
        c_flags = _flags_to_int(flags)
        _check_flags(c_flags)
        c_flags |= libev.EVFLAG_NOENV
        c_flags |= libev.EVFLAG_FORKCHECK
        if default is None:
            default = True
            if _default_loop_destroyed:
                default = False
        if default:
            self._ptr = libev.gevent_ev_default_loop(c_flags)
            if not self._ptr:
                raise SystemError("ev_default_loop(%s) failed" % (c_flags,))
        else:
            self._ptr = libev.ev_loop_new(c_flags)
            if not self._ptr:
                raise SystemError("ev_loop_new(%s) failed" % (c_flags,))
        if default or globals()["__SYSERR_CALLBACK"] is None:
            set_syserr_cb(self._handle_syserr)
        libev.ev_prepare_start(self._ptr, self._prepare)
        self.unref()
        libev.ev_check_start(self._ptr, self._check)
        self.unref()
        self._keepaliveset = set()

    def _check_callback_handle_error(self, t, v, tb):
        self.handle_error(None, t, v, tb)

    def _check_callback(self, *args):
        pass

    def _run_callbacks(self, _evloop, _, _revents):
        count = 1000
        libev.ev_timer_stop(self._ptr, self._timer0)
        while self._callbacks:
            if count > 0:
                callbacks = self._callbacks
                self._callbacks = []
                for cb in callbacks:
                    self.unref()
                    callback = cb.callback
                    args = cb.args
                    if not callback is None:
                        if args is None:
                            pass
                        else:
                            cb.callback = None
                            try:
                                callback(*args)
                            except:
                                try:
                                    self.handle_error(cb, *sys.exc_info())
                                except:
                                    try:
                                        print(
                                            "Exception while handling another error",
                                            file=sys.stderr,
                                        )
                                        traceback.print_exc()
                                    except:
                                        pass

                            finally:
                                cb.args = None
                                count -= 1

        if self._callbacks:
            libev.ev_timer_start(self._ptr, self._timer0)

    def _stop_aux_watchers(self):
        if libev.ev_is_active(self._prepare):
            self.ref()
            libev.ev_prepare_stop(self._ptr, self._prepare)
        if libev.ev_is_active(self._check):
            self.ref()
            libev.ev_check_stop(self._ptr, self._check)

    def destroy(self):
        global _default_loop_destroyed
        if self._ptr:
            self._stop_aux_watchers()
            if globals()["__SYSERR_CALLBACK"] == self._handle_syserr:
                set_syserr_cb(None)
            if libev.ev_is_default_loop(self._ptr):
                _default_loop_destroyed = True
            libev.ev_loop_destroy(self._ptr)
            self._ptr = ffi.NULL

    @property
    def ptr(self):
        return self._ptr

    @property
    def WatcherType(self):
        return watcher

    @property
    def MAXPRI(self):
        return libev.EV_MAXPRI

    @property
    def MINPRI(self):
        return libev.EV_MINPRI

    def _handle_syserr(self, message, errno):
        try:
            errno = os.strerror(errno)
        except:
            traceback.print_exc()

        try:
            message = "%s: %s" % (message, errno)
        except:
            traceback.print_exc()

        self.handle_error(None, SystemError, SystemError(message), None)

    def handle_error(self, context, type, value, tb):
        handle_error = None
        error_handler = self.error_handler
        if error_handler is not None:
            handle_error = getattr(error_handler, "handle_error", error_handler)
            handle_error(context, type, value, tb)
        else:
            self._default_handle_error(context, type, value, tb)

    def _default_handle_error(self, context, type, value, tb):
        traceback.print_exception(type, value, tb)
        libev.ev_break(self._ptr, libev.EVBREAK_ONE)

    def run(self, nowait=False, once=False):
        flags = 0
        if nowait:
            flags |= libev.EVRUN_NOWAIT
        if once:
            flags |= libev.EVRUN_ONCE
        libev.ev_run(self._ptr, flags)

    def reinit(self):
        libev.ev_loop_fork(self._ptr)

    def ref(self):
        libev.ev_ref(self._ptr)

    def unref(self):
        libev.ev_unref(self._ptr)

    def break_(self, how=libev.EVBREAK_ONE):
        libev.ev_break(self._ptr, how)

    def verify(self):
        libev.ev_verify(self._ptr)

    def now(self):
        return libev.ev_now(self._ptr)

    def update(self):
        libev.ev_now_update(self._ptr)

    def __repr__(self):
        return "<%s at 0x%x %s>" % (self.__class__.__name__, id(self), self._format())

    @property
    def default(self):
        if libev.ev_is_default_loop(self._ptr):
            return True
        else:
            return False

    @property
    def iteration(self):
        return libev.ev_iteration(self._ptr)

    @property
    def depth(self):
        return libev.ev_depth(self._ptr)

    @property
    def backend_int(self):
        return libev.ev_backend(self._ptr)

    @property
    def backend(self):
        backend = libev.ev_backend(self._ptr)
        for key, value in _flags:
            if key == backend:
                return value

        return backend

    @property
    def pendingcnt(self):
        return libev.ev_pending_count(self._ptr)

    def io(self, fd, events, ref=True, priority=None):
        return io(self, fd, events, ref, priority)

    def timer(self, after, repeat=0.0, ref=True, priority=None):
        return timer(self, after, repeat, ref, priority)

    def signal(self, signum, ref=True, priority=None):
        return signal(self, signum, ref, priority)

    def idle(self, ref=True, priority=None):
        return idle(self, ref, priority)

    def prepare(self, ref=True, priority=None):
        return prepare(self, ref, priority)

    def check(self, ref=True, priority=None):
        return check(self, ref, priority)

    def fork(self, ref=True, priority=None):
        return fork(self, ref, priority)

    def async(self, ref=True, priority=None):
        return async(self, ref, priority)

    if sys.platform != "win32":

        def child(self, pid, trace=0, ref=True):
            return child(self, pid, trace, ref)

        def install_sigchld(self):
            libev.gevent_install_sigchld_handler()

        def reset_sigchld(self):
            libev.gevent_reset_sigchld_handler()

    def stat(self, path, interval=0.0, ref=True, priority=None):
        return stat(self, path, interval, ref, priority)

    def callback(self, priority=None):
        return callback(self, priority)

    def run_callback(self, func, *args):
        cb = callback(func, args)
        self._callbacks.append(cb)
        self.ref()
        return cb

    def _format(self):
        if not self._ptr:
            return "destroyed"
        else:
            msg = self.backend
            if self.default:
                msg += " default"
            msg += " pending=%s" % self.pendingcnt
            msg += self._format_details()
            return msg

    def _format_details(self):
        msg = ""
        fileno = self.fileno()
        try:
            activecnt = self.activecnt
        except AttributeError:
            activecnt = None

        if activecnt is not None:
            msg += " ref=" + repr(activecnt)
        if fileno is not None:
            msg += " fileno=" + repr(fileno)
        return msg

    def fileno(self):
        if self._ptr:
            fd = self._ptr.backend_fd
            if fd >= 0:
                return fd

    @property
    def activecnt(self):
        if not self._ptr:
            raise ValueError("operation on destroyed loop")
        return self._ptr.activecnt


_NOARGS = ()


class callback(object):
    __slots__ = ("callback", "args")

    def __init__(self, callback, args):
        self.callback = callback
        self.args = args or _NOARGS

    def stop(self):
        self.callback = None
        self.args = None

    def __nonzero__(self):
        return self.args is not None

    __bool__ = __nonzero__

    @property
    def pending(self):
        return self.callback is not None

    def _format(self):
        return ""

    def __repr__(self):
        result = "<%s at 0x%x" % (self.__class__.__name__, id(self))
        if self.pending:
            result += " pending"
        if self.callback is not None:
            result += " callback=%r" % (self.callback,)
        if self.args is not None:
            result += " args=%r" % (self.args,)
        if self.callback is None:
            if self.args is None:
                result += " stopped"
        return result + ">"


class watcher(object):
    def __init__(self, _loop, ref=True, priority=None, args=_NOARGS):
        self.loop = _loop
        if ref:
            self._flags = 0
        else:
            self._flags = 4
        self._args = None
        self._callback = None
        self._handle = ffi.new_handle(self)
        self._watcher = ffi.new(self._watcher_struct_pointer_type)
        self._watcher.data = self._handle
        if priority is not None:
            libev.ev_set_priority(self._watcher, priority)
        self._watcher_init(self._watcher, self._watcher_callback, *args)

    _watcher_type = None
    _watcher_init = None
    _watcher_start = None
    _watcher_stop = None
    _watcher_struct_pointer_type = None
    _watcher_callback = None

    @classmethod
    def _init_subclasses(cls):
        for subclass in cls.__subclasses__():
            watcher_type = subclass._watcher_type
            subclass._watcher_struct_pointer_type = ffi.typeof(
                "struct " + watcher_type + "*"
            )
            subclass._watcher_callback = ffi.addressof(
                libev, "_gevent_generic_callback"
            )
            for name in ("start", "stop", "init"):
                ev_name = watcher_type + "_" + name
                watcher_name = "_watcher_" + name
                if getattr(subclass, watcher_name) is None:
                    setattr(subclass, watcher_name, getattr(libev, ev_name))

    def __repr__(self):
        formats = self._format()
        result = "<%s at 0x%x%s" % (self.__class__.__name__, id(self), formats)
        if self.pending:
            result += " pending"
        if self.callback is not None:
            result += " callback=%r" % (self.callback,)
        if self.args is not None:
            result += " args=%r" % (self.args,)
        if self.callback is None:
            if self.args is None:
                result += " stopped"
        result += " handle=%s" % self._watcher.data
        return result + ">"

    def _format(self):
        return ""

    def _libev_unref(self):
        if self._flags & 6 == 4:
            self.loop.unref()
            self._flags |= 2

    def _get_ref(self):
        if self._flags & 4:
            return False
        else:
            return True

    def _set_ref(self, value):
        if value:
            if not self._flags & 4:
                return
            if self._flags & 2:
                self.loop.ref()
            self._flags &= -7
        else:
            if self._flags & 4:
                return
            self._flags |= 4
            if not self._flags & 2:
                if libev.ev_is_active(self._watcher):
                    self.loop.unref()
                    self._flags |= 2

    ref = property(_get_ref, _set_ref)

    def _get_callback(self):
        return self._callback

    def _set_callback(self, cb):
        if not callable(cb):
            if cb is not None:
                raise TypeError("Expected callable, not %r" % (cb,))
        self._callback = cb

    callback = property(_get_callback, _set_callback)

    def _get_args(self):
        return self._args

    def _set_args(self, args):
        if not isinstance(args, tuple):
            if args is not None:
                raise TypeError("args must be a tuple or None")
        self._args = args

    args = property(_get_args, _set_args)

    def start(self, callback, *args):
        if callback is None:
            raise TypeError("callback must be callable, not None")
        self.callback = callback
        self.args = args or _NOARGS
        self._libev_unref()
        self.loop._keepaliveset.add(self)
        self._watcher_start(self.loop._ptr, self._watcher)

    def stop(self):
        if self._flags & 2:
            self.loop.ref()
            self._flags &= -3
        self._watcher_stop(self.loop._ptr, self._watcher)
        self.loop._keepaliveset.discard(self)
        self._callback = None
        self.args = None

    def _get_priority(self):
        return libev.ev_priority(self._watcher)

    def _set_priority(self, priority):
        if libev.ev_is_active(self._watcher):
            raise AttributeError("Cannot set priority of an active watcher")
        libev.ev_set_priority(self._watcher, priority)

    priority = property(_get_priority, _set_priority)

    def feed(self, revents, callback, *args):
        self.callback = callback
        self.args = args or _NOARGS
        if self._flags & 6 == 4:
            self.loop.unref()
            self._flags |= 2
        libev.ev_feed_event(self.loop._ptr, self._watcher, revents)
        if not self._flags & 1:
            self._flags |= 1

    @property
    def active(self):
        if libev.ev_is_active(self._watcher):
            return True
        else:
            return False

    @property
    def pending(self):
        if libev.ev_is_pending(self._watcher):
            return True
        else:
            return False


class io(watcher):
    _watcher_type = "ev_io"

    def __init__(self, loop, fd, events, ref=True, priority=None):
        if fd < 0:
            raise ValueError("fd must be non-negative: %r" % fd)
        if events & ~(libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE):
            raise ValueError("illegal event mask: %r" % events)
        watcher.__init__(self, loop, ref=ref, priority=priority, args=(fd, events))

    def start(self, callback, *args, **kwargs):
        args = args or _NOARGS
        if kwargs.get("pass_events"):
            args = (GEVENT_CORE_EVENTS,) + args
        watcher.start(self, callback, *args)

    def _get_fd(self):
        return vfd_get(self._watcher.fd)

    def _set_fd(self, fd):
        if libev.ev_is_active(self._watcher):
            raise AttributeError(
                "'io' watcher attribute 'fd' is read-only while watcher is active"
            )
        vfd = vfd_open(fd)
        vfd_free(self._watcher.fd)
        self._watcher_init(
            self._watcher, self._watcher_callback, vfd, self._watcher.events
        )

    fd = property(_get_fd, _set_fd)

    def _get_events(self):
        return self._watcher.events

    def _set_events(self, events):
        if libev.ev_is_active(self._watcher):
            raise AttributeError(
                "'io' watcher attribute 'events' is read-only while watcher is active"
            )
        self._watcher_init(
            self._watcher, self._watcher_callback, self._watcher.fd, events
        )

    events = property(_get_events, _set_events)

    @property
    def events_str(self):
        return _events_to_str(self._watcher.events)

    def _format(self):
        return " fd=%s events=%s" % (self.fd, self.events_str)


class timer(watcher):
    _watcher_type = "ev_timer"

    def __init__(self, loop, after=0.0, repeat=0.0, ref=True, priority=None):
        if repeat < 0.0:
            raise ValueError("repeat must be positive or zero: %r" % repeat)
        watcher.__init__(self, loop, ref=ref, priority=priority, args=(after, repeat))

    def start(self, callback, *args, **kw):
        update = kw.get("update", True)
        if update:
            libev.ev_now_update(self.loop._ptr)
        watcher.start(self, callback, *args)

    @property
    def at(self):
        return self._watcher.at

    def again(self, callback, *args, **kw):
        self._watcher_start = libev.ev_timer_again
        try:
            self.start(callback, *args, **kw)
        finally:
            del self._watcher_start


class signal(watcher):
    _watcher_type = "ev_signal"

    def __init__(self, loop, signalnum, ref=True, priority=None):
        if signalnum < 1 or signalnum >= signalmodule.NSIG:
            raise ValueError("illegal signal number: %r" % signalnum)
        watcher.__init__(self, loop, ref=ref, priority=priority, args=(signalnum,))


class idle(watcher):
    _watcher_type = "ev_idle"


class prepare(watcher):
    _watcher_type = "ev_prepare"


class check(watcher):
    _watcher_type = "ev_check"


class fork(watcher):
    _watcher_type = "ev_fork"


class async(watcher):
    _watcher_type = "ev_async"

    def send(self):
        libev.ev_async_send(self.loop._ptr, self._watcher)

    @property
    def pending(self):
        if libev.ev_async_pending(self._watcher):
            return True
        else:
            return False


class child(watcher):
    _watcher_type = "ev_child"

    def __init__(self, loop, pid, trace=0, ref=True):
        if not loop.default:
            raise TypeError("child watchers are only available on the default loop")
        loop.install_sigchld()
        watcher.__init__(self, loop, ref=ref, args=(pid, trace))

    def _format(self):
        return " pid=%r rstatus=%r" % (self.pid, self.rstatus)

    @property
    def pid(self):
        return self._watcher.pid

    @property
    def rpid(self):
        return self._watcher.rpid

    @rpid.setter
    def rpid(self, value):
        self._watcher.rpid = value

    @property
    def rstatus(self):
        return self._watcher.rstatus

    @rstatus.setter
    def rstatus(self, value):
        self._watcher.rstatus = value


class stat(watcher):
    _watcher_type = "ev_stat"

    @staticmethod
    def _encode_path(path):
        if isinstance(path, bytes):
            return path
        else:
            encoding = sys.getfilesystemencoding() or "utf-8"
            try:
                path = path.encode(encoding, "surrogateescape")
            except LookupError:
                raise UnicodeEncodeError("Can't encode path to filesystem encoding")

            return path

    def __init__(self, _loop, path, interval=0.0, ref=True, priority=None):
        self._paths = self._encode_path(path)
        self._path = path
        self._cpath = ffi.new("char[]", self._paths)
        watcher.__init__(
            self, _loop, ref=ref, priority=priority, args=(self._cpath, interval)
        )

    @property
    def path(self):
        return self._path

    @property
    def attr(self):
        if not self._watcher.attr.st_nlink:
            return
        else:
            return self._watcher.attr

    @property
    def prev(self):
        if not self._watcher.prev.st_nlink:
            return
        else:
            return self._watcher.prev

    @property
    def interval(self):
        return self._watcher.interval


watcher._init_subclasses()


def _syserr_cb(msg):
    global __SYSERR_CALLBACK
    try:
        msg = ffi.string(msg)
        __SYSERR_CALLBACK(msg, ffi.errno)
    except:
        set_syserr_cb(None)
        raise


_syserr_cb._cb = ffi.callback("void(*)(char *msg)", _syserr_cb)


def set_syserr_cb(callback):
    global __SYSERR_CALLBACK
    if callback is None:
        libev.ev_set_syserr_cb(ffi.NULL)
        __SYSERR_CALLBACK = None
    else:
        if callable(callback):
            libev.ev_set_syserr_cb(_syserr_cb._cb)
            __SYSERR_CALLBACK = callback
        else:
            raise TypeError("Expected callable or None, got %r" % (callback,))


__SYSERR_CALLBACK = None
LIBEV_EMBED = True
